package com.beeasy.hzbpm.ctrl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.github.llyb120.nami.core.MultipartFile;
import com.github.llyb120.nami.ctrl.Ctrl;
import com.github.llyb120.json.Arr;
import com.github.llyb120.json.Json;
import com.github.llyb120.json.Obj;
import com.mongodb.client.model.UpdateOptions;
import org.bson.Document;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static com.beeasy.hzbpm.bean.MongoService.db;
import static com.github.llyb120.json.Json.a;
import static com.github.llyb120.json.Json.o;

public class dep extends Ctrl {
    static String tempDir = System.getProperty("java.io.tmpdir");

    public Arr list() {
        return menu.tree(db.getCollection("dep")
            .aggregate(a(
                o("$sort", o("sort", 1)),
                o("$project",o(
                    "_id", 0
                ))
            ).toBson())
            .into(a()), "pid", "id");
    }


    public Object getUsers() {
        Obj users = db.getCollection("user")
            .aggregate(a(
                o("$match", o(
                    "orgs", o(
                        "$elemMatch", o(
                            "id", $get.s("id")
//                            "type", o(
//                                "$ne", "ROLE"
//                            )
                        )
                    )
                )),
                o("$unwind", "$orgs"),
                o("$match", o(
                    "orgs.type", o("$ne", "ROLE")
                )),
                o("$project", o(
                    "orgs", "$orgs",
                    "uid", "$id",
                    "_id", 0,
                    "name", o(
                        "$concat", a("$true_name", "(", "$username", ")")
                    )
                ))
            ).toBson())
            .into(a())
            .group(e -> ((Document)(((Document)e).get("orgs"))).getString("type"));
        return users;
    }

    /**
     * 保存部门
     */
    public void save(){
        String id = $post.s("id", "");
        String name = $request.ss("name").trim();
        if(name.isEmpty()){
            error("部门名不能为空");
        }
        $post.ii("sort");
        Obj doc = o(
            "id", id,
            "name", name,
            "sort", $post.ii("sort"),
            "pid", $request.get("parent_id")
//            "parent_id", $request.get("parent_id"),
//            "type", type(),
//            "tag_info", $post.aa("tag_info")
        );
        if(id.isEmpty()){
            //同目录下不能有相同的
            long count = db.getCollection("dep")
                .count(o(
                    "name", name,
                    "pid",$request.get("pid")
                ).toBson());
            if(count > 0){
                error("已经有同名部门");
            }
            doc.put("id", IdUtil.objectId());
        } else {
            long count = db.getCollection("dep")
                .count(o(
                    "name", name,
                    "pid", $request.get("pid"),
                    "id", o("$ne", id)
                ).toBson());
            if(count > 0){
                error("已经有同名部门");
            }
        }
        db.getCollection("dep")
            .replaceOne(o("id", doc.ss("id")).toBson(), doc.toBson(), new UpdateOptions().upsert(true));
    }

    /**
     * 删除部门
     */
    public void del(){
        //删除角色
        db.getCollection("dep")
            .deleteOne(o(
                "id", $request.s("id")
            ).toBson());
        //删除用户归属
        db.getCollection("user")
            .updateMany(
                o(
                    "orgs", o("$elemMatch", o(
                        "id", $request.s("id"),
                        "type", o("$ne", "ROLE")
                    ))
                ).toBson(),
                o(
                    "$pull", o(
                        "orgs", o(
                            "id", $request.s("id"),
                            "type", o("$ne", "ROLE")
                        )
                    )
                ).toBson()
            );
    }


    /**
     * 从部门移除用户
     */
    public void delUser(){
        db.getCollection("user")
            .updateOne(
                o(
                    "id", $request.s("uid")
                ).toBson(),
                o(
                    "$pull", o(
                        "orgs", o(
                            "id", $request.s("oid"),
                            "type", ($request.s("type"))
                        )
                    )
                ).toBson()
            );
    }

    /**
     * 给部门添加用户
     */
    public void addUser() {
        db.getCollection("user")
            .updateOne(
                o(
                    "id", $request.s("uid"),
                    "orgs", o(
                        "$not", o(
                            "$elemMatch", o(
                                "id", $request.s("oid"),
                                "type", ($request.s("type"))
                            )
                        )
                    )
                ).toBson(),
                o(
                    "$push", o(
                        "orgs", o(
                            "id", $request.s("oid"),
                            "type", ($request.s("type"))
                        )
                    )
                ).toBson()
            );
    }


        /**
         * 遍历部门
         * @param writer
         * @param list
         * @param i
         * @param parName
         */
    private void walk(ExcelWriter writer, Arr<?> list, AtomicInteger i, String parName){
        for (Obj obj : list.oa()) {
            String name = obj.ss("name").trim();
            if(name.isEmpty()){
                continue;
            }
            writer.writeCellValue(0, i.get(), name);
            writer.writeCellValue(1, i.get(), obj.ii("sort"));
            writer.writeCellValue(2, i.get(), parName.isEmpty() ? "\\" : parName);
            i.incrementAndGet();
            walk(writer, obj.aa("children"), i, parName + "\\" + name);
        }
    }

    /**
     * 导出部门
     * @return
     */
    public MultipartFile export() {
        File temp = new File(tempDir, StrUtil.uuid() + ".xlsx");
        ExcelWriter writer = new ExcelWriter(temp);
        String[] columns = {"部门名称", "部门排序", "上级部门"};
        writer.setColumnWidth(0, 50);
        writer.setColumnWidth(2, 80);
        for (int i = 0; i < columns.length; i++) {
            writer.writeCellValue(i, 0, columns[i]);
        }
        Arr list = list();
        walk(writer, list, new AtomicInteger(1), "");
        writer.flush(temp);
        writer.close();
        return new MultipartFile("部门导出" + DateUtil.formatDate(new Date()) + ".xlsx", temp, true);
    }

    public void imt(MultipartFile file) throws IOException {
        byte[] bs = file.getBytes();
        ExcelReader reader = ExcelUtil.getReader(new ByteArrayInputStream(bs));
        List<Map<String, Object>> list = reader.readAll();
        List<Object> head = reader.readRow(0);
        if(head.size() != 3){
            error("导入失败");
        }
        List<Obj> newlist = list.stream()
            .map(Json::ooo)
            .map(e -> {
                return o(
                    "id", IdUtil.objectId(),
                    "parent_id", null,
                    "type", "DEPARTMENT",
                    "sort", e.ii((String) head.get(1)),
                    "tag_info", a(),
                    "name", e.ss((String) head.get(0)).trim(),
                    "source_parent", e.ss((String) head.get(2)).trim()
                );
            })
            .filter(e -> e.ss("name").isEmpty())
            .collect(Collectors.toList());



    }

}
